<template>
  <div>
    <h1>侦听器 watchEffect</h1>
    <p>
      watch 的第一个参数可以是不同形式的“数据源”：它可以是一个 ref
      (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组：
    </p>
    <div>inputVal: <input type="text" v-model="inputVal" /></div>

    <div>
      <label for="">num1:</label>
      <input type="number" v-model="num1" />
      <label for="">num2:</label>
      <input type="number" v-model="num2" />
      <div>求和：{{ sumNum }}</div>
    </div>
    <hr />
    <div>
      <input type="text" v-model="ruser.name" />
      <input type="text" v-model="ruser.sex" />
      <input type="text" v-model="ruser.love.lanqiu" />
    </div>

    <hr />
    <div
      ref="my-input"
      style="width: 100px; height: 100px; background-color: aqua"
      v-if="isShow"
    ></div>
    <button type="button" @click="changeShow">显示正方形</button>
  </div>
</template>

<script lang="ts">
export default {
  name: 'Study3StuDemo16'
}
</script>
<script setup lang="ts">
import { computed, reactive, ref, useTemplateRef, watch, watchEffect } from 'vue'

// ref (包括计算属性)
const inputVal = ref('默认值')
const num1 = ref(0)
const num2 = ref(0)

const ruser = reactive({
  name: '站起来',
  sex: '男',
  love: {
    lanqiu: '喜欢'
  }
})

const isShow = ref(false)
const inputDom = useTemplateRef('my-input')

const changeShow = () => {
  isShow.value = true
}

// #回调的触发时机
// 默认情况下，侦听器回调会在父组件更新 (如有) 之后、所属组件的 DOM 更新之前被调用。
// 这意味着如果你尝试在侦听器回调中访问所属组件的 DOM，那么 DOM 将处于更新前的状态。
// watchEffect(() => {
//   console.log(isShow.value, '1:watchEffect:inputVal')
//   console.log(inputDom.value, '#watchEffect###inputDom.value')
// })

// watch(isShow, () => {
//   console.log(inputDom.value, '#watchEffect###inputDom.value')
// })

// 如果想在侦听器回调中能访问被 Vue 更新之后的所属组件的 DOM，你需要指明 flush: 'post' 选项：
watch(
  isShow,
  () => {
    console.log(inputDom.value, '#watchEffect:post###inputDom.value')
  },
  {
    flush: 'post'
  }
)

// watch(inputVal, (newVal, oldVal) => {
//   console.log(newVal, 'ref:newVal')
//   console.log(oldVal, 'ref:oldVal')
// })

watchEffect(() => {
  console.log(inputVal.value, '1:watchEffect:inputVal')
})

// 计算属性
const sumNum = computed(() => {
  return num1.value + num2.value
})
// 监听计算属性
// watch(sumNum, (newVal, oldVal) => {
//   console.log(newVal, 'computed:newVal')
//   console.log(oldVal, 'computed:oldVal')
// })

watchEffect(() => {
  console.log(sumNum.value, '2:watchEffect:sumNum.value')
})

// getter 函数
// watch(
//   () => inputVal.value,
//   (newVal, oldVal) => {
//     console.log(newVal, 'getter:newVal')
//     console.log(oldVal, 'getter:oldVal')
//   }
// )

watchEffect(() => {
  console.log((() => inputVal.value)(), '3:watchEffect:(() => inputVal.value)()')
})

// getter 函数2
// watch(
//   () => num1.value * num2.value,
//   (newVal, oldVal) => {
//     console.log('num1.value * num2.value')

//     console.log(newVal, 'getter2:newVal')
//     console.log(oldVal, 'getter2:oldVal')
//   }
// )

watchEffect(() => {
  const num66 = (() => num1.value * num2.value)()

  console.log(num66, '4:watchEffect:( () => num1.value * num2.value)()')
})

// 多个数据源组成的数组
// watch(
//   [inputVal, () => num1.value * num2.value, () => inputVal.value, () => num1.value + num2.value],
//   ([val1, val2, val3, val4]) => {
//     console.log(val1, 'arr1:newVal')
//     console.log(val2, 'arr2:newVal')
//     console.log(val3, 'arr3:newVal')
//     console.log(val4, 'arr4:newVal')
//   }
// )

// 但是对于有多个依赖项的侦听器来说，使用 watchEffect() 可以消除手动维护依赖列表的负担
watchEffect(() => {
  const [cheng, ival, sum] = [
    (() => num1.value * num2.value)(),
    (() => inputVal.value)(),
    (() => num1.value + num2.value)()
  ]

  console.log(
    cheng,
    ival,
    sum,
    '#5watchEffect:[inputVal, () => num1.value * num2.value, () => inputVal.value, () => num1.value + num2.value]'
  )
})

// 如果你需要侦听一个嵌套数据结构中的几个属性，watchEffect() 可能会比深度侦听器更有效，
// 因为它将只跟踪回调中被使用到的属性，而不是递归地跟踪所有的属性。
watchEffect(() => {
  console.log(ruser.love.lanqiu, '7watchEffect:ruser.love.lanqiu')
})

watchEffect(() => {
  console.log(ruser.name)
  console.log(ruser.love.lanqiu, '8watchEffect:ruser.love.lanqiu')
})

// 这种直接使用ref的方式，值在变化的时候侦听不到
watchEffect(() => {
  console.log(inputVal, '6:我就不value')
})
</script>

<style></style>
